package datatypes;

import homeMadeExceptions.Bd_AddrException;
import host.DiscoveryNetworkSocket;
import host.RoutingNetworkSocket;

import java.lang.reflect.Method;
import java.util.Vector;

import simulationEngine.SimulationEngine;

import miniworld.LocalSimulationQueue;



public class Host {
//Variables
	private int hostID = -1;
	private BluetoothDeviceAddress bd_addr = null;
	private boolean active = false;
	//ID of the engine, this is not the ID of the DB Simulation
	private int SimulationID = -1;
	private int ScenarioID = -1;
	private Vector<String> services = null;
	private LinkMode LM = LinkMode.NONE;
	
	
	//the Network Capabilities
	private String sourcePackageRouting = "host.routingProtocol.";
	private String sourcePackageDiscovery = "host.discoveryProtocol.";
	
	private RoutingNetworkSocket routingSocket = null;
	private DiscoveryNetworkSocket discoverySocket = null;
	
	
	//DISCOVERY MECHANISM
	private DiscoveryMechanismEnum discoveryMechanism = DiscoveryMechanismEnum.FloodingRequest;
	
	
	private LocalSimulationQueue locQueue = new LocalSimulationQueue (this);
	  
	
	
//Methods
	
	public Host (String myID, boolean active, Vector<String> services, int Simulation) {
		
			try {
				this.hostID = Integer.parseInt(myID);
				this.active = active;
				this.SimulationID = Simulation;
				this.discoveryMechanism = SimulationEngine.getNextDiscMechanism();
				this.services = services;
				this.bd_addr = new BluetoothDeviceAddress(hostID + ":" + hostID + ":" + hostID + ":" + hostID + ":" + hostID + ":" + hostID);
			} catch (NumberFormatException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Bd_AddrException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}		 
	}
	
	public boolean isEqual (int id){
		return this.hostID == id;
	}

	public boolean isEqual (String id){
		try {
			return this.hostID == Integer.parseInt(id);
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	public boolean isEqual (BluetoothDeviceAddress bd_Addr){
		return this.bd_addr.isEqual(bd_Addr);
	}

	public int getID (){
		return hostID;
	}
	
	public void setActive(boolean newState){
		this.active = newState;
	}
	
	public boolean isActive(){
		return this.active;
	}
	
	public void setScenarioID (int ScenarioID){
		this.ScenarioID = ScenarioID;
	}
	
	public int getScenarioID (){
		return this.ScenarioID;
	}
	
	public int getSimulationID(){
		return this.SimulationID;
	}
	
	//returns the ID of the simulation engine, where the host belongs to
	public int getSimulationEngineID (){
		return this.SimulationID;
	}
	
	public BluetoothDeviceAddress getBd_Addr(){
		return this.bd_addr;
	}
	
	public LinkMode getLM(){
		return this.LM;
	}
	@SuppressWarnings("unchecked")
	public RoutingNetworkSocket getRoutingSocket (){
		if(routingSocket == null){
			try {
				Class cls = Class.forName(this.sourcePackageRouting + this.getRoutingProtocol());
				Method method = cls.getMethod("getSocket", Host.class);  
				routingSocket = (RoutingNetworkSocket) method.invoke(null, this);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
				
		}
		return routingSocket;
	}

	@SuppressWarnings("unchecked")
	public DiscoveryNetworkSocket getDiscoverySocket (){
		if(discoverySocket == null){
			try {
				Class cls = Class.forName(this.sourcePackageDiscovery + this.getDiscoveryProtocol());
				Method method = cls.getMethod("getSocket", Host.class);  
				discoverySocket = (DiscoveryNetworkSocket) method.invoke(null, this);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return discoverySocket;
	}

	public void changeLM (LinkMode newMode){
		this.LM = newMode;
	}
	
	private String getRoutingProtocol (){
		return DiscoveryMechanismMapper.getRoutingProtocol(this.getDiscoveryMechanism());
	}
	
	private String getDiscoveryProtocol (){
		return DiscoveryMechanismMapper.getDiscoverProtocol(this.getDiscoveryMechanism());
	}
	
	public LocalSimulationQueue getLocalQueue (){
		return this.locQueue;
	}
	
	public Vector<String> getServices (){
		if (this.services == null){
			this.services = new Vector<String>();
		}
		return this.services;
	}
	
	public DiscoveryMechanismEnum getDiscoveryMechanism(){
		return this.discoveryMechanism;
	}
}
